# LeetCode 136、只出现一次的数字

# 一、题目描述

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例1 :

输入: [2,2,1]
输出: 1

示例 2:

输入: [4,1,2,1,2]
输出: 4

# 二、题目解析

为了满足 算法应该具有线性时间复杂度不使用额外空间来实现,本题通过寻找位运算规律来解决。

假设 a = 1, b = 0

1、 1 ⊕ 0 = 1, 0 ⊕ 0 = 0 => a ⊕ 0 = 1, b ⊕ 0 = 0 ==> 任何数与0做异或运算结果均为其本身

2、 1 ⊕ 1 = 0, 0 ⊕ 0 = 0 => a ⊕ a = 0, b ⊕ b = 0 ==> 任何数与其本身做异或运算结果均为0

3、 1 ⊕ 0 ⊕ 1 = 0 => 1 ⊕ 1 = 0 => a ⊕ b ⊕ a = b

​ 1 ⊕ 1 ⊕ 0 = 0 => 0 ⊕ 0 = 0 => a ⊕ a ⊕ b = b

​ 0 ⊕ (1 ⊕ 1) = 0 => 0 ⊕ 0 = 0 => b ⊕ (a ⊕ a) = b

​ ==>异或运算满足交换律和结合律

由于 非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次, 即数组中元素数量恒为奇数。

假设数组中有2n+1个元素,有n个元素为出现两次的元素,如果所有数进行连续异或操作可得:

  A1 ⊕ A1 ⊕ A2 ⊕ A2 ...... ⊕ An ⊕ An ⊕ An+1
= (A1 ⊕ A1) ⊕ (A2 ⊕ A2) ...... ⊕ (An ⊕ An) ⊕ An+1      //通过规律3
= (0) ⊕ (0) ...... ⊕ (0) ⊕ An+1                        //通过规律2
= An+1                                                 //通过规律1

通过规律1可知,我们在做连续异或操作的时候,可以以0为起始数开始运算。

# 三、参考代码

class Solution {
    public int singleNumber(int[] nums) {
        int single = 0;
        for (int num : nums) {
            single ^= num;
        }
        return single;
    }
}

# 四、复杂度分析

时间复杂度:O(n)

空间复杂度:O(1)